﻿using System;
using QLNet;
using FinPlusCommon;
using p = FinPlusAnalytics.QLConvParser;
using u = FinPlusUtility.Utility;

namespace FinPlusAnalytics
{
    public static class QLConvParser
    {
        public static string PayRec(string value)
        {
            switch (value.ToLower())
            {
                case "pay":
                case "payer":
                case "p":
                    return "Payer";
                case "rec":
                case "receiver":
                case "r":
                    return "Receiver";
                default:
                    throw new AnalyticsFormatException(string.Format("payrec {0} not recognised", value));
            }
        }

        public static string LongShort(string value)
        {
            switch (value.ToLower())
            {
                case "short":
                case "sell":
                case "s":
                case "pay":
                case "payer":
                case "p":
                    return "Short";
                case "buy":
                case "b":
                case "long":
                case "rec":
                case "receiver":
                case "r":
                    return "Long";
                default:
                    throw new AnalyticsFormatException(string.Format("long short {0} not recognised", value));
            }
        }

        public static string BuyerSeller(string value)
        {
            switch (value.ToLower())
            {
                case "short":
                case "sell":
                case "s":
                case "pay":
                case "payer":
                case "p":
                    return "Seller";
                case "buy":
                case "b":
                case "long":
                case "rec":
                case "receiver":
                case "r":
                    return "Buyer";
                default:
                    throw new AnalyticsFormatException(string.Format("long short {0} not recognised", value));
            }
        }

        public static Period GetPeriod(string period)
        {
            var p = u.RemoveNumeric(period);
            var n = 1;

            int.TryParse(u.RemoveAlpha(period), out n);

            switch (p.ToLower())
            {
                case "days":
                case "d":
                    return new Period(Frequency.Daily) * n;
                case "weeks":
                case "w":
                    return new Period(Frequency.Weekly) * n;
                case "months":
                case "m":
                    return new Period(Frequency.Monthly) * n;
                case "years":
                case "y":
                    return new Period(Frequency.Annual) * n;
                default:
                    throw new AnalyticsFormatException(string.Format("period {0} not recognised", period)); 
            }
        }

        public static Calendar Calendar(string holidays)
        {
            switch (holidays.ToLower())
            {
                case "usd:govt":
                    return new UnitedStates();
                case "usd:nyse":
                    return new UnitedStates();
                case "tgt":
                case "target":
                case "":
                    return new TARGET();
                default:
                    throw new AnalyticsFormatException(string.Format("holidays {0} not recognised", holidays)); 
            }
        }

        public static DayCounter DayCount(string dayCount)
        {
            switch(dayCount.ToLower())
            {
                case "30/360:bondbasis":
                    return new Thirty360(Thirty360.Thirty360Convention.BondBasis);
	            case "euro30/360":
                    return new Thirty360(Thirty360.Thirty360Convention.European); 
	            case "act/360":
                    return new Actual360(); 
	            case "act/365:fixed":
                    return new Actual365Fixed();
                case "act/act:isda":
	                return new ActualActual(ActualActual.Convention.ISDA);
                case "act/act:bond":
                    return new ActualActual(ActualActual.Convention.Bond);
	            default:
                    throw new AnalyticsFormatException(string.Format("day count {0} not recognised", dayCount));
            }
        }

        public static BusinessDayConvention BizConv(string bizConv)
        {
            try
            {
                return u.EnumParse<BusinessDayConvention>(bizConv);
            }
            catch(Exception e)
            {
                throw new AnalyticsFormatException(string.Format("biz conv {0} not recognised", bizConv),e);
            }
        }

        public static Frequency Freq(string frequency)
        {
            try
            {
                return u.EnumParse<Frequency>(frequency);
            }
            catch(Exception e)
            {
                throw new AnalyticsFormatException(string.Format("frequency {0} not recognised", frequency), e);
            }
        }

        public static Compounding Compounding(string compounding)
        {
            try
            {
                return u.EnumParse<Compounding>(compounding);
            }
            catch(Exception e)
            {
                throw new AnalyticsFormatException(string.Format("compounding {0} not recognised", compounding), e);
            }
        }

        public static IborIndex Index(string indexType, string tenor, string marketName, string curveName)
        {
            try
            {
                var yeildTermStructure = new Handle<YieldTermStructure>( Markets.Instance.GetMarket(marketName).GetCurve(curveName));

                switch(string.Format("{0}{1}", indexType.ToLower(), tenor.ToLower()))
                {
                    case "euribor1m": return new Euribor1M(yeildTermStructure);
                    case "euribor3m": return new Euribor3M(yeildTermStructure);
                    case "euribor6m": return new Euribor6M(yeildTermStructure);
                    case "euribor1y": return new Euribor1Y(yeildTermStructure);
                    case "usdlibor1m": return new USDLibor(p.GetPeriod(tenor), yeildTermStructure);
                    case "usdlibor3m": return new USDLibor(p.GetPeriod(tenor), yeildTermStructure);
                    case "usdlibor6m": return new USDLibor(p.GetPeriod(tenor), yeildTermStructure);
                    case "usdlibor1y": return new USDLibor(p.GetPeriod(tenor), yeildTermStructure);
                    default: throw new AnalyticsFormatException(string.Format("index {}{} not found", indexType, tenor));
                }
            }
            catch(Exception e)
            {
                throw new AnalyticsException(string.Format("indexType {0} not recognised", indexType), e);
            }
        }
    }
}
